package org.adream.account.rest.api;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.adream.account.entity.OcrIdCardEntity;
import org.adream.account.entity.RealNameAuthEntity;
import org.adream.account.model.ResultModel;
import org.adream.account.rest.api.model.DataTableRequest;
import org.adream.account.rest.api.model.DataTableResponse;
import org.adream.account.rest.api.model.RealNameAuthSearchForm;
import org.adream.account.service.OcrService;
import org.adream.account.service.RealNameAuthService;
import org.adream.account.util.Constant;
import org.adream.account.util.SensorDataUtil;
import org.adream.account.util.UserUtil;
import org.adream.account.util.Utils;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.validation.Assertion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.cas.authentication.CasAuthenticationToken;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;

/**
 *	实名认证 
 */
@RequestMapping("/realNameAuth")
@Controller
public class RealNameAuthApiController {

	private final static Logger logger = LoggerFactory.getLogger(RealNameAuthApiController.class);

	@Autowired
	private RealNameAuthService authService;

	@Value("${image.file.path.verifypic}")
	private String verifyPicPath;

	@Autowired
	private OcrService ocrService;
	
	
	/**
	 * "实名认证"管理审核"实名认证"(后台管理)
	 * 
	 * @param realNameAuthEntity
	 * @return
	 */
	@RequestMapping(value = "/checkAuth", produces = "application/json;charset=UTF-8", method = RequestMethod.POST)
	@ResponseBody
	public ResultModel<?> checkAuth(RealNameAuthEntity realNameAuthEntity) {
		if (realNameAuthEntity == null || StringUtils.isEmpty(realNameAuthEntity.getUid())
				|| StringUtils.isEmpty(realNameAuthEntity.getCheckResult())) {
			logger.warn("审核失败,参数为空:(");
			return new ResultModel<String>(ResultModel.ERR_PARAM, "审核失败,参数有误", null);
		}
		// 验证数据长度
		if (realNameAuthEntity.getCheckResult().length() > Constant.LONG_DATA_LENGTH) {
			logger.warn("审核失败,认证结果数据太长,认证结果数据长度:" + realNameAuthEntity.getCheckResult().length());
			return new ResultModel<String>(ResultModel.WARN_DATA_LENGTH, "认证结果输入过长,请精简", null);
		}
		return authService.checkAuthAndSynData(realNameAuthEntity);
	}

	/**
	 * 不存在新增,存在更新(前端提交) 改---------身份证实名的不用这个接口 ， ☆此处只包括了 护照审核 ☆ creType = 1
	 * 
	 * @param uid
	 * @param realNameAuthEntity
	 * @return
	 */
	@RequestMapping(value = "/replaceAuth", produces = "application/json;charset=UTF-8", method = RequestMethod.POST)
	@ResponseBody
	public ResultModel<?> replaceAuth(@RequestParam String p_realName, @RequestParam String p_creNum,
			@RequestPart(value = "p_frontPic", required = false) MultipartFile frontPic, HttpServletRequest request) {
		String uid = UserUtil.getUidByRequest(request);
		String icon = request.getSession().getServletContext().getRealPath("/normal/images/tip.png");
		if (StringUtils.isEmpty(uid)) {
			return new ResultModel<String>(ResultModel.ERR_PARAM, "系统错误,请联系管理员", null);
		}
		Map<String, Object> properties = new HashMap<>();
		properties.put("document_type", "护照");
		properties.put("is_success", false);
		if (StringUtils.isEmpty(p_realName) || StringUtils.isEmpty(p_creNum)) {
			properties.put("failure_reason", "系统错误");
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
			
			return new ResultModel<String>(ResultModel.ERR_PARAM, "系统错误96,请联系管理员", null);
		}
		if (p_realName.length() > Constant.COMMON_DATA_LENGTH) {
			properties.put("failure_reason", "真实姓名输入过长");
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);

			return new ResultModel<String>(ResultModel.WARN_DATA_LENGTH, "真实姓名输入过长,请精简", null);
		}
		if (p_creNum.length() > Constant.LONG_DATA_LENGTH) {
			properties.put("failure_reason", "证件号输入过长");
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
			
			return new ResultModel<String>(ResultModel.WARN_DATA_LENGTH, "证件号输入过长,请精简", null);
		}
		RealNameAuthEntity realNameAuthEntity = new RealNameAuthEntity();
		realNameAuthEntity.setRealName(p_realName);
		realNameAuthEntity.setCreNum(p_creNum);
		realNameAuthEntity.setUid(uid);
		realNameAuthEntity.setCreType(Constant.ONE);
		realNameAuthEntity.setDr(Constant.ONE);
		if (!StringUtils.isEmpty(frontPic) && frontPic.getSize() > Constant.ZERO) {
			String[] frontPicArray = Utils.dealPicFile(frontPic, verifyPicPath);
			if (frontPicArray.length == Constant.ONE) {
				realNameAuthEntity.setCreFrontPic(frontPicArray[0]);
			} else {
				realNameAuthEntity.setCreFrontPic(Utils.otherPicExt2Jpg(frontPicArray[1]));
				try {
					boolean frontResult = Utils.compressAndAddWatermark(frontPic.getInputStream(),
							Constant.DEFAULT_COMPRESS_SCALE, icon,
							frontPicArray[0] + realNameAuthEntity.getCreFrontPic());
					if (!frontResult) {
						properties.put("failure_reason", "图片上传失败");
						SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
						
						return new ResultModel<String>(ResultModel.ERR_PARAM, "更新失败,图片上传失败", null);
					}
				} catch (IOException e) {
					logger.warn("正面证件照上传失败:)");
					properties.put("failure_reason", "图片上传失败");
					SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
					return new ResultModel<String>(ResultModel.ERR_PARAM, "更新失败,图片上传失败", null);
				}
			}
		}
		// 处理证件号是否使用过
		String rltMsg = authService.vaildateIdCard(realNameAuthEntity.getUid(), realNameAuthEntity.getCreNum());
		if (StringUtils.isEmpty(rltMsg)) {
			realNameAuthEntity.setState(Constant.ONE);
			realNameAuthEntity.setCheckResult("正在审核中,请耐心等候");
		} else {
			realNameAuthEntity.setState(Constant.THREE);
			realNameAuthEntity.setCheckResult(rltMsg);
		}
		RealNameAuthEntity realNameAuth = authService.queryAuthByUid(uid);
		boolean flag = false;
		// 是否已申请实名认证
		if (realNameAuth == null) {
			flag = authService.addRealNameAuth(realNameAuthEntity);
			if (!flag) {
				properties.put("failure_reason", "系统错误");
				SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
				// 若进行了审核操作,需埋点'盒子_实名认证审核结果'事件
				if (realNameAuthEntity.getState() != null && realNameAuthEntity.getState() != Constant.ONE) {
					Map<String, Object> idCardResultMap = new HashMap<>();
					idCardResultMap.put("document_type", "护照");
					idCardResultMap.put("is_audit", realNameAuthEntity.getState() == Constant.TWO ? true : false);
					idCardResultMap.put("failure_reason",
							realNameAuthEntity.getState() == Constant.TWO ? "" : realNameAuthEntity.getCheckResult());
					SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD_RESULT, idCardResultMap);
				}
				
				return new ResultModel<String>(ResultModel.ERR_PARAM, "系统错误151,请联系管理员", null);
			}
			properties.put("is_success", true);
			properties.put("failure_reason", "");
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
			
			return new ResultModel<String>(ResultModel.SUCCESS, "新增成功", null);
		}
		// 已申请过实名认证
		String oriCreNum = realNameAuth.getCreNum();
		// 若前端提交的是之前存在的记录带*的creNum
		if (!StringUtils.isEmpty(realNameAuthEntity.getCreNum()) && realNameAuthEntity.getCreNum().indexOf("*") != -1) {
			// creType和creNum与之前提交的数据一致
			if (realNameAuthEntity.getCreType() == realNameAuth.getCreType()
					&& realNameAuthEntity.getCreNum().equals(Utils.replaceXing(realNameAuth.getCreNum(), 3, 4))) {
				realNameAuthEntity.setCreNum(oriCreNum);
			} else {
				logger.warn("更新失败,请求参数有误:(creType: " + realNameAuthEntity.getCreType() + ",creNum:"
						+ realNameAuthEntity.getCreNum() + ")");
				properties.put("failure_reason", "系统错误");
				SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
				
				return new ResultModel<String>(ResultModel.ERR_PARAM, "更新失败,请求参数有误", null);
			}
		}
		Utils.copyPropertiesIgnoreNull(realNameAuthEntity, realNameAuth);
		// 护照不需要背面照，以前如果身份认证有的 清空
		realNameAuth.setCreReversePic(null);
		flag = authService.updateRealNameAuth(realNameAuth);
		if (!flag) {
			properties.put("failure_reason", "系统错误");
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
			
			return new ResultModel<String>(ResultModel.ERR_PARAM, "实名认证失败", null);
		}
		properties.put("is_success", true);
		properties.put("failure_reason", "");
		SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
		//若进行了审核操作,需埋点'盒子_实名认证审核结果'事件
		if(realNameAuth.getState() != null && realNameAuth.getState() != Constant.ONE) {						
			Map<String, Object> idCardResultMap = new HashMap<>();
			idCardResultMap.put("document_type", "护照");
			idCardResultMap.put("is_audit", realNameAuth.getState() == Constant.TWO ? true : false);
			idCardResultMap.put("failure_reason", realNameAuth.getState() == Constant.TWO ? "" : realNameAuth.getCheckResult());
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD_RESULT, idCardResultMap);
		}
		return new ResultModel<String>(ResultModel.SUCCESS, "更新成功", null);
	}

	/**
	 * 删除
	 * 
	 * @param uid
	 * @return
	 */
	@RequestMapping(value = "/{uid}", produces = "application/json;charset=UTF-8", method = RequestMethod.DELETE)
	@ResponseBody
	public ResultModel<?> deleteRealNameAuth(@PathVariable("uid") String uid) {
		if (StringUtils.isEmpty(uid)) {
			return new ResultModel<String>(ResultModel.ERR_PARAM, "删除失败,请求参数有误", null);
		}
		return authService.deleteRealNameAuth(uid);
	}

	/**
	 * 根据uid,删除标志查询
	 * 
	 * @param uid
	 * @param dr
	 * @return
	 */
	@RequestMapping(value = "/uid/{uid}/dr/{dr}", produces = "application/json;charset=UTF-8", method = RequestMethod.GET)
	@ResponseBody
	public ResultModel<RealNameAuthEntity> queryRealNameAuthByUidAndDr(@PathVariable("uid") String uid, @PathVariable("dr") Integer dr,
			HttpServletRequest request) {
		uid = (uid != null) ? uid : UserUtil.getUidByRequest(request);
		if (StringUtils.isEmpty(uid) || StringUtils.isEmpty(dr)) {
			return new ResultModel<RealNameAuthEntity>(ResultModel.ERR_PARAM, "查询失败,请求参数有误", null);
		}
		RealNameAuthEntity realNameAuth = authService.queryAuthByUidAndDr(uid, dr);
		if(realNameAuth == null) {
			return new ResultModel<RealNameAuthEntity>(ResultModel.NOT_FOUND_OBJECT, "查询失败,数据不存在", null);
		}
		return new ResultModel<RealNameAuthEntity>(ResultModel.SUCCESS, "查询成功", realNameAuth);
	}

	/**
	 * 根据删除标志,当前uid
	 * 
	 * @param dr
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/dr/{dr}/uid", produces = "application/json;charset=UTF-8", method = RequestMethod.GET)
	@ResponseBody
	public ResultModel<?> queryRealNameAuthByCurUidAndDr(@PathVariable("dr") Integer dr, HttpServletRequest request) {
		String uid = UserUtil.getUidByRequest(request);
		if (StringUtils.isEmpty(uid) || StringUtils.isEmpty(dr)) {
			return new ResultModel<String>(ResultModel.ERR_PARAM, "查询失败,请求参数有误", null);
		}
		RealNameAuthEntity realNameAuth = authService.queryAuthByUidAndDr(uid, dr);
		if (realNameAuth == null) {
			return new ResultModel<RealNameAuthEntity>(ResultModel.NOT_FOUND_OBJECT, "未查询到相应数据", null);
		}
		realNameAuth.setCreNum(Utils.replaceXing(realNameAuth.getCreNum(), Constant.THREE, Constant.FOUR));
		return new ResultModel<RealNameAuthEntity>(ResultModel.SUCCESS, "查询成功", realNameAuth);
	}

	/**
	 * 根据删除标志查询
	 * 
	 * @param dr 删除标志
	 * @return
	 */
	@RequestMapping(value = "/dr/{dr}", produces = "application/json;charset=UTF-8", method = RequestMethod.GET)
	@ResponseBody
	public ResultModel<?> queryRealNameAuthByDr(@PathVariable("dr") Integer dr) {
		if (StringUtils.isEmpty(dr)) {
			return new ResultModel<String>(ResultModel.ERR_PARAM, "查询失败,请求参数有误", null);
		}
		List<RealNameAuthEntity> realNameAuths = authService.queryRealNameAuthsByDr(dr);
		if (Utils.isEmptyCollection(realNameAuths)) {
			return new ResultModel<String>(ResultModel.NOT_FOUND_OBJECT, "查询失败,无相关数据", null);
		}
		return new ResultModel<List<RealNameAuthEntity>>(ResultModel.SUCCESS, "查询成功", realNameAuths);
	}

	/**
	 * 分页查询
	 * 
	 * @param form 请求表单
	 * @return
	 */
	@RequestMapping(value = "/selectPageAuth", produces = "application/json;charset=UTF-8", method = RequestMethod.POST)
	@ResponseBody
	public ResultModel<?> selectPageAuth(@RequestBody RealNameAuthSearchForm form) {
		if (form == null || StringUtils.isEmpty(form.getDr())) {
			return new ResultModel<String>(ResultModel.ERR_PARAM, "查询失败,请求参数有误", null);
		}
		PageInfo<RealNameAuthEntity> page = authService.selectPageAuth(form.getUid(), form.getRealName(),
				form.getCreType(), form.getState(), form.getDr(), form.getPageNo(), form.getPageSize());
		if (page == null || page.getList() == null || page.getList().size() == Constant.ZERO) {
			return new ResultModel<String>(ResultModel.NOT_FOUND_OBJECT, "未查询到相应的realNameAuth", null);
		}
		return new ResultModel<PageInfo<RealNameAuthEntity>>(ResultModel.SUCCESS, "查询成功", page);
	}

	/**
	 * 单次校验图片
	 * 
	 * @param cardType 身份证正反面 0：正面 , 1：反面
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/vaildateAuthImg", produces = "application/json;charset=UTF-8", method = RequestMethod.POST)
	@ResponseBody
	public ResultModel<?> vaildateAuthImg(Integer cardType,
			@RequestPart(value = "file", required = false) MultipartFile file, HttpServletRequest request) {
		String uid = UserUtil.getUidByRequest(request);
		String icon = request.getSession().getServletContext().getRealPath("/normal/images/tip.png");
		if (StringUtils.isEmpty(uid)) {
			return new ResultModel<String>(ResultModel.ERR_PARAM, "操作失败,请求参数有误", null);
		}
		String picName = null;
		if (!StringUtils.isEmpty(file) && file.getSize() > Constant.ZERO) {
			String[] frontPicArray = Utils.getFileName(file, verifyPicPath);

			picName = Utils.otherPicExt2Jpg(frontPicArray[1]);
			try {
				boolean frontResult = Utils.compressAndAddWatermark(file.getInputStream(),
						Constant.DEFAULT_COMPRESS_SCALE, icon, frontPicArray[0] + picName);
				if (!frontResult) {
					return new ResultModel<String>(ResultModel.ERR_PARAM, "更新失败,图片上传失败", null);
				}
			} catch (IOException e) {
				logger.warn(cardType + "面证件照上传失败:)");
				return new ResultModel<String>(ResultModel.ERR_PARAM, "更新失败,图片上传失败", null);
			}

		}
		OcrIdCardEntity ocrIdCardEntity = null;
		try {
			ocrIdCardEntity = ocrService.processOCR(uid, cardType, picName);
		} catch (FileNotFoundException e) {

		} catch (IOException e) {

		}

		// ocr未处理 /处理不成功的 但是图片已经上传的 保存图片名字
		// 不是真实的OCR数据 返回页面 统一封装 ，不要放入名字和身份证号
		if (ocrIdCardEntity == null) {
			ocrIdCardEntity = new OcrIdCardEntity();
			ocrIdCardEntity.setOcrCode("0");
			ocrIdCardEntity.setCardType(cardType);
		}
		// ocr数据库中 图片可能不是自己的那张 很小情况发生这种 此处保证不会出错
		ocrIdCardEntity.setFilename(picName);
		return new ResultModel<OcrIdCardEntity>(ResultModel.SUCCESS, "操作成功", ocrIdCardEntity);
	}
	
	/**
	 *	验证证件号码是否被占用
	 * @param creNum
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/vaildateCreNum/{creNum}", produces = "application/json;charset=UTF-8", method = RequestMethod.GET)
	@ResponseBody
	public ResultModel<?> vaildateCreNum(@PathVariable("creNum") String creNum, HttpServletRequest request) {
		String uid = UserUtil.getUidByRequest(request);
		if (StringUtils.isEmpty(uid) || StringUtils.isEmpty(creNum) || StringUtils.isEmpty(creNum.trim())) {
			return new ResultModel<String>(ResultModel.ERR_PARAM, "操作失败,请求参数有误", null);
		}
		String rltMsg = authService.vaildateIdCard(uid, creNum);
		if (rltMsg != null) {
			return new ResultModel<String>(ResultModel.ERR_USER_INFO, "用户身份信息已存在", rltMsg);
		}
		return new ResultModel<String>(ResultModel.SUCCESS, "操作完成", null);
	}

	/**
	 * 实名认证（身份证认证）
	 * 
	 * @param realNameAuthEntity
	 * @return
	 */
	@RequestMapping(value = "idCardAuth", produces = "application/json;charset=UTF-8", method = RequestMethod.POST)
	@ResponseBody
	public ResultModel<?> idCardAuth(@RequestBody String jsonString, HttpServletRequest request) {
		String uid = UserUtil.getUidByRequest(request);
		if (StringUtils.isEmpty(uid)) {
			return new ResultModel<String>(ResultModel.ERR_PARAM, "系统错误402,请联系管理员", null);
		}
		//神策数据'盒子_用户提交实名认证'事件埋点
		Map<String, Object> properties = new HashMap<>();
		properties.put("document_type", "身份证");
		properties.put("is_success", false);
		if (StringUtils.isEmpty(jsonString)) {
			properties.put("failure_reason", "系统错误");
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
			return new ResultModel<String>(ResultModel.ERR_PARAM, "系统错误405,请联系管理员", null);
		}
		JSONObject jsonObject = JSONObject.parseObject(jsonString);
		RealNameAuthEntity realNameAuthEntity = (RealNameAuthEntity) JSONObject.toJavaObject(jsonObject,
				RealNameAuthEntity.class);
		if (realNameAuthEntity == null) {
			properties.put("failure_reason", "系统错误");
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
			return new ResultModel<String>(ResultModel.ERR_PARAM, "系统错误410,请联系管理员", null);
		}
		if (realNameAuthEntity.getCreType() == null || realNameAuthEntity.getCreType() != 0) {
			properties.put("failure_reason", "系统错误");
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
			return new ResultModel<String>(ResultModel.ERR_PARAM, "系统错误413,请联系管理员", null);
		}
		if (StringUtils.isEmpty(realNameAuthEntity.getCreFrontPic())
				|| StringUtils.isEmpty(realNameAuthEntity.getCreReversePic())) {
			properties.put("failure_reason", "系统错误");
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
			return new ResultModel<String>(ResultModel.ERR_PARAM, "系统错误417,请联系管理员", null);
		}
		// 数据长度校验
		if (realNameAuthEntity.getRealName() != null
				&& realNameAuthEntity.getRealName().length() > Constant.COMMON_DATA_LENGTH) {
			properties.put("failure_reason", "真实姓名输入过长");
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
			return new ResultModel<String>(ResultModel.WARN_DATA_LENGTH, "真实姓名输入过长,请精简", null);
		}
		if (realNameAuthEntity.getCreNum() != null
				&& realNameAuthEntity.getCreNum().length() > Constant.LONG_DATA_LENGTH) {
			properties.put("failure_reason", "证件号输入过长");
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
			return new ResultModel<String>(ResultModel.WARN_DATA_LENGTH, "证件号输入过长,请精简", null);
		}
		realNameAuthEntity.setUid(uid);
		realNameAuthEntity.setDr(Constant.ONE);

		// 处理身份证是否使用过(之前已做过验证，正式提交再做一次验证)
		String rltMsg = authService.vaildateIdCard(realNameAuthEntity.getUid(), realNameAuthEntity.getCreNum());
		if (StringUtils.isEmpty(rltMsg)) {
			realNameAuthEntity.setState(Constant.ONE);
			realNameAuthEntity.setCheckResult("正在审核中,请耐心等候");
		} else {
			realNameAuthEntity.setState(Constant.THREE);
			realNameAuthEntity.setCheckResult(rltMsg);
		}
		RealNameAuthEntity realNameAuth = authService.queryAuthByUid(uid);
		boolean flag = false;
		if (realNameAuth == null) { // 第一次申请实名认证
			flag = authService.addRealNameAuth(realNameAuthEntity);
			if (!flag) {
				properties.put("failure_reason", "系统错误");
				SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
				return new ResultModel<String>(ResultModel.ERR_PARAM, "系统错误454,请联系管理员", null);
			}
			// 实名认证处理 状态是 1（审核中） 的
			if (realNameAuthEntity.getState() != null && realNameAuthEntity.getState() == Constant.ONE) {
				ocrService.autoRealName(realNameAuthEntity);
			}
			properties.put("is_success", true);
			properties.put("failure_reason", "");
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
			//若进行了审核操作,需埋点'盒子_实名认证审核结果'事件
			if(realNameAuthEntity.getState() != null && realNameAuthEntity.getState() != Constant.ONE) {						
				Map<String, Object> idCardResultMap = new HashMap<>();
				idCardResultMap.put("document_type", "身份证");
				idCardResultMap.put("is_audit", realNameAuthEntity.getState() == Constant.TWO ? true : false);
				idCardResultMap.put("failure_reason", realNameAuthEntity.getState() == Constant.TWO ? "" : realNameAuthEntity.getCheckResult());
				SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD_RESULT, idCardResultMap);
			}
			return new ResultModel<String>(ResultModel.SUCCESS, "新增成功", null);
		}

		// 已申请过实名认证
		String oriCreNum = realNameAuth.getCreNum();
		// 若前端提交的是之前存在的记录带*的creNum
		if (!StringUtils.isEmpty(realNameAuthEntity.getCreNum()) && realNameAuthEntity.getCreNum().indexOf("*") != -1) {
			// creType和creNum与之前提交的数据一致
			if (realNameAuthEntity.getCreType() == realNameAuth.getCreType()
					&& realNameAuthEntity.getCreNum().equals(Utils.replaceXing(realNameAuth.getCreNum(), 3, 4))) {
				realNameAuthEntity.setCreNum(oriCreNum);
			} else {
				logger.warn("更新失败,请求参数有误:(creType: " + realNameAuthEntity.getCreType() + ",creNum:"
						+ realNameAuthEntity.getCreNum() + ")");
				properties.put("failure_reason", "系统错误");
				SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
				return new ResultModel<String>(ResultModel.ERR_PARAM, "系统错误477,请联系管理员", null);
			}
		}
		Utils.copyPropertiesIgnoreNull(realNameAuthEntity, realNameAuth);
		// 1
		flag = authService.updateRealNameAuth(realNameAuth);
		if (!flag) {
			properties.put("failure_reason", "系统错误");
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
			return new ResultModel<String>(ResultModel.ERR_PARAM, "实名认证失败，请稍后重试", null);
		}
		// 实名认证处理 状态是 1（审核中） 的
		if (realNameAuth.getState() != null && realNameAuth.getState() == Constant.ONE) {
			ocrService.autoRealName(realNameAuth);
		}
		properties.put("is_success", true);
		properties.put("failure_reason", "");
		SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD, properties);
		//若进行了审核操作,需埋点'盒子_实名认证审核结果'事件
		if(realNameAuth.getState() != null && realNameAuth.getState() != Constant.ONE) {						
			Map<String, Object> idCardResultMap = new HashMap<>();
			idCardResultMap.put("document_type", "身份证");
			idCardResultMap.put("is_audit", realNameAuth.getState() == Constant.TWO ? true : false);
			idCardResultMap.put("failure_reason", realNameAuth.getState() == Constant.TWO ? "" : realNameAuth.getCheckResult());
			SensorDataUtil.saTrack(uid, true, Constant.SENSOR_DATA_ADREAMBOX_IDCARD_RESULT, idCardResultMap);
		}
		return new ResultModel<String>(ResultModel.SUCCESS, "更新成功", null);
	}
	
	/**
	 * 以dataTable形式 查询认证信息
	 * @param dp
	 * @return
	 */
	@RequestMapping(value = "/queryAuthByDataTable", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public DataTableResponse<RealNameAuthEntity> queryAuthByDataTable(@RequestBody DataTableRequest dp) {

		// 目前设置为全部实名通过的
		String extendsWhere = "and state = 2 ";
		dp.setExtendsWhere(extendsWhere);

		PageInfo<RealNameAuthEntity> pif = authService.queryAuthByDataTable(dp);
		DataTableResponse<RealNameAuthEntity> dtr = new DataTableResponse<RealNameAuthEntity>();
		dtr.setData(pif.getList());
		dtr.setDraw(dp.getDraw());
		dtr.setRecordsFiltered(pif.getTotal());
		dtr.setRecordsFiltered(pif.getTotal());
		return dtr;
	}
	
	/**
	 * 根据权限 查看认证图片
	 * @param uid
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "downloadPic", produces = "application/json;charset=UTF-8", method = RequestMethod.GET)
	@ResponseBody
	public HttpServletResponse download(String uid, HttpServletRequest request, HttpServletResponse response) {
		if (StringUtils.isEmpty(uid)) {
			return response;
		}
		// 只有查看实名权限方可下载
		Object o = new Object();
		o = request.getUserPrincipal();
		if (o == null || !(o instanceof CasAuthenticationToken)) {
			PrintWriter out = null;
			try {
				response.setContentType("text/html;charset=UTF-8");
				out = response.getWriter();
				out.write("登录信息失效,请重新登录");
				return response;
			} catch (IOException e) {
				logger.warn("图片下载失败:" + e.getMessage());
				return response;
			} finally {
				if (out != null) {
					out.close();
				}
			}
		}
		// 获取登录信息
		CasAuthenticationToken token = (CasAuthenticationToken) o;
		Assertion assertion = token.getAssertion();
		AttributePrincipal principal = assertion.getPrincipal();
		Map<String, Object> map = principal.getAttributes();
		if (StringUtils.isEmpty(map.get("uid"))) {
			PrintWriter out = null;
			try {
				response.setContentType("text/html;charset=UTF-8");
				out = response.getWriter();
				out.write("登录信息失效,请重新登录");
				return response;
			} catch (IOException e) {
				logger.warn("图片下载失败:" + e.getMessage());
				return response;
			} finally {
				if (out != null) {
					out.close();
				}
			}
		}
		// 获取全部权限
		String resIdStr = (String) map.get("resIds");
		// 权限为空 || (既没有实名认证管理权限又没有身份认证管理权限)
		if (StringUtils.isEmpty(resIdStr) || resIdStr.indexOf(Constant.REALNAME_SHOW_RES_ID) == -1) {
			PrintWriter out = null;
			try {
				response.setContentType("text/html;charset=UTF-8");
				out = response.getWriter();
				out.write("下载权限不足");
				return response;
			} catch (IOException e) {
				logger.warn("图片下载失败:" + e.getMessage());
				return response;
			} finally {
				if (out != null) {
					out.close();
				}
			}
		}
		String path = verifyPicPath.endsWith(File.separator + "") ? verifyPicPath : verifyPicPath + File.separator;
		RealNameAuthEntity authEntity = authService.queryAuthByUid(uid);
		if (authEntity == null) {
			return response;
		}
		List<File> files = new ArrayList<>();
		files.add(new File(path + authEntity.getCreFrontPic()));// 正面
		files.add(new File(path + authEntity.getCreReversePic()));// 背面

		String num = authEntity.getCreNum();
		num = StringUtils.isEmpty(num) ? "" : num.length() > 6 ? num.substring(num.length() - 6) :num;
		String downloadName = authEntity.getRealName() + num + ".zip";

		ZipOutputStream zipOutStream = null;
		OutputStream outputStream = null;
		try {

			downloadName = java.net.URLEncoder.encode(downloadName, "UTF-8");
			response.reset();
			response.setContentType("application/octet-stream");
			response.setHeader("Content-Disposition", "attachment;fileName*=UTF-8''" + downloadName);

			outputStream = response.getOutputStream();
			// -- 将多个文件压缩写进响应的输出流

			// -- 包装成ZIP格式输出流
			zipOutStream = new ZipOutputStream(new BufferedOutputStream(outputStream));
			// -- 设置压缩方法
			zipOutStream.setMethod(ZipOutputStream.DEFLATED);
			// -- 将多文件循环写入压缩包
			for (int i = 0; i < files.size(); i++) {
				File file = files.get(i);
				FileInputStream filenputStream = new FileInputStream(file);
				byte[] data = new byte[(int) file.length()];
				filenputStream.read(data);
				// -- 添加ZipEntry，并ZipEntry中写入文件流，这里，加上i是防止要下载的文件有重名的导致下载失败
				if (i == 0) {
					// 正面 后缀名
					String aSuffix = authEntity.getCreFrontPic().substring(authEntity.getCreFrontPic().indexOf("."));
					zipOutStream.putNextEntry(new ZipEntry(authEntity.getRealName() + num + "(正面)" + aSuffix ));
				} else {
					// 背面
					String bSuffix = authEntity.getCreFrontPic().substring(authEntity.getCreReversePic().indexOf("."));
					zipOutStream.putNextEntry(new ZipEntry(authEntity.getRealName() + num + "(背面)" + bSuffix ));
				}

				zipOutStream.write(data);
				filenputStream.close();
				zipOutStream.closeEntry();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (Objects.nonNull(zipOutStream)) {
					zipOutStream.flush();
					zipOutStream.close();
				}
				if (Objects.nonNull(outputStream)) {
					outputStream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		return response;
	}
}